import log from '../../../helpers/logger';
import axios from 'axios';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';
import {
  dateToTimestampWithTimezone
} from '../../../helpers/utilsJS';
import {
  getFirstWechatopenFromDatabase
} from '../../../services/uctoo/wechatopen';
import {
  createWechatReply,
  deleteWechatReplyFromDatabase,
  editWechatReplyInDatabase,
  getWechatReplyFromDatabase,
  getWechatReplysFromDatabase,
  queryWechatReplysFromDatabase
} from '../../../services/uctoo/wechat_reply';
import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { wechatopen } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import { OpenPlatform, ServerRequest, FormData, defineOpenPlatformConfig } from 'node-easywechat';
import RedisCacher from '../../../lib/RedisCacher';
import redisClient from '../../../lib/redis';
import { PrismaClient } from '../../../../../prisma/generated/uctoo'

const db = new PrismaClient({
  log: ['query', 'info', 'warn', 'error'],
});
import DbCacher from '../../../lib/DbCacher';
import { queryWechatopenAppletsFromDatabase } from '../../../services/uctoo/wechatopen_applet';
  //#region AutoCreateCode
import {
  createWechatopen,
  deleteWechatopenFromDatabase,
  deleteMultiWechatopenFromDatabase,
  editWechatopenInDatabase,
  editMultiWechatopenInDatabase,
  getWechatopenFromDatabase,
  getWechatopensFromDatabase,
  queryWechatopensFromDatabase,
  countWechatopens
} from '../../../services/uctoo/wechatopen';

class uctooWechatopenController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooWechatopen = showSelectedObjectKeys(body, keysArray) as wechatopen;
    uctooWechatopen.creator = userId;

    return uctooWechatopen;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooWechatopen = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooWechatopen) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdWechatopen = await createWechatopen(uctooWechatopen);
      if (!createdWechatopen) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdWechatopen);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooWechatopen = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatopen) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatopen = await editMultiWechatopenInDatabase(uctooWechatopen, JSON.parse(ids), user);
        
        if (typeof editedWechatopen === 'object' && 'success' in editedWechatopen) {
          if (!editedWechatopen.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedWechatopen.reason,
              ...(editedWechatopen.wechatopenId && { wechatopenId: editedWechatopen.wechatopenId })
            });
          }
          return res.status(200).json(editedWechatopen.data);
        }
        
        res.status(200).json(editedWechatopen);
      }else{
        const uctooWechatopen = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatopen) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatopen = await editWechatopenInDatabase(uctooWechatopen, uctooWechatopen.id, user);
        
        if (typeof editedWechatopen === 'object' && 'success' in editedWechatopen) {
          if (!editedWechatopen.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedWechatopen.reason });
          }
          return res.status(200).json(editedWechatopen.data);
        }
        res.status(200).json(editedWechatopen);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiWechatopenFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.wechatopenId && { wechatopenId: deletionResult.wechatopenId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteWechatopenFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const wechatopenFromDb = await getWechatopenFromDatabase(id, user);
      if (!wechatopenFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(wechatopenFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countWechatopens(user);
      
      if (query) {
        const wechatopensFromDb = await queryWechatopensFromDatabase(limit, page, skip, query, user);
        if (!wechatopensFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatopens: wechatopensFromDb
        });
      } else {
        const wechatopensFromDb = await getWechatopensFromDatabase(limit, skip, page, user);
        if (!wechatopensFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatopens: wechatopensFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode

  public getFirstFromDb: defaultRouteHandler = async (req, res) => {

    try {
      const wechatopensFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      log.info({ info: 'wechatopensFromDb', wechatopensFromDb });
      res.status(200).json(wechatopensFromDb);

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public componentVerifyTicket: defaultRouteHandler = async (req, res) => {

    try {
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      // 检查wechatopenFromDb是否存在及包含必要字段
      if (!wechatopenFromDb) {
        log.error({ err: 'No valid wechatopen configuration found', desc: 'Database query returned null' });
        return res.status(500).json({ err: 'System configuration error', desc: 'No valid wechatopen configuration found' });
      }
      
      log.info({ info: 'wechatopensFromDb', wechatopenFromDb });
      
      // 检查必要字段是否存在
      const requiredFields = ['appid', 'appsecret', 'token', 'encoding_aes_key'];
      const missingFields = requiredFields.filter(field => !wechatopenFromDb[field]);
      
      if (missingFields.length > 0) {
        log.error({ err: 'Missing required fields in wechatopen configuration', missingFields: missingFields });
        return res.status(500).json({ err: 'System configuration error', desc: `Missing required fields: ${missingFields.join(', ')}` });
      }

      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      
      log.info({ info: 'wechatopenConfig', app_id: wechatopenConfig.app_id });
      
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);

      const body = await req.text();
      log.info({ info: 'request_body', body: body });

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();

      wxserver.with(async function (message) {
        log.info({ info: 'wxserver.with', message });
        if (message) {
          log.info({ info: 'message.InfoType', InfoType: message.InfoType });
        }
        if (message && message.InfoType == 'component_verify_ticket') {

          log.info({ info: 'component_verify_ticket', component_verify_ticket: message.ComponentVerifyTicket });
          //判断component_access_token是否过期或快过期
          const tokenID = 'open_platform.component_access_token.' + wechatopenFromDb['appid'];
          log.info({ info: 'tokenID', tokenID: tokenID });
          const currentToken = await db.app_access_token.findFirst({
            where: {
              id: tokenID,
            },
          });
          if (currentToken) {  //已有component_access_token缓存
            const dateWithTimezone = new Date(currentToken['token_overtime']); // 
            const tokenOvertimeTimestamp = dateToTimestampWithTimezone(dateWithTimezone);
            log.info({ info: 'tokenOvertimeTimestamp', timestamp: tokenOvertimeTimestamp }); // 输出时间戳
            const nowTimestamp = Date.now();
            const expiresTimestamp = nowTimestamp + 20 * 60 * 1000;
            const expiresDate = new Date(expiresTimestamp);
            const expires_in = expiresDate.toISOString();
            if (expiresTimestamp >= tokenOvertimeTimestamp) {  //差20分钟过期，重新获取component_access_token
              //得先删除原缓存数据
              await Dbcacher.delete(tokenID);

              const oldToken = wxopen.getComponentAccessToken();
              //  log.info({ info: 'oldToken', oldToken: oldToken });
              const newToken = await oldToken.getToken();
              log.info({ info: 'newToken', newToken: newToken });
              const date = new Date(nowTimestamp + 120 * 60 * 1000);  //component_access_token两小时过期
              const newTokenOvertime = date.toISOString();
              await db.app_access_token.upsert({
                where: {
                  id: tokenID,
                },
                update: {
                  access_token: newToken,
                  token_overtime: newTokenOvertime

                },
                create: {
                  id: tokenID,
                  access_token: newToken,
                  token_overtime: newTokenOvertime

                },
              });
              //同步wechatopen表的数据,但以app_access_token的数据为准
              const editedWechatopen = await editWechatopenInDatabase({ component_verify_ticket: message.ComponentVerifyTicket, component_access_token: newToken, token_overtime: newTokenOvertime }, wechatopenFromDb['id']);

            }
          } else { //没有component_access_token缓存
            const nowTimestamp = Date.now();
            const oldToken = wxopen.getComponentAccessToken();
            // log.info({ info: 'oldToken', oldToken: oldToken });
            const newToken = await oldToken.getToken();
            log.info({ info: 'newToken', newToken: newToken });
            const date = new Date(nowTimestamp + 120 * 60 * 1000);  //component_access_token两小时过期
            const newTokenOvertime = date.toISOString();
            await db.app_access_token.upsert({
              where: {
                id: tokenID,
              },
              update: {
                access_token: newToken,
                token_overtime: newTokenOvertime

              },
              create: {
                id: tokenID,
                access_token: newToken,
                token_overtime: newTokenOvertime

              },
            });
            //同步wechatopen表的数据,但以app_access_token的数据为准
            const editedWechatopen = await editWechatopenInDatabase({ component_verify_ticket: message.ComponentVerifyTicket, component_access_token: newToken, token_overtime: newTokenOvertime }, wechatopenFromDb['id']);
          }
          //此处作为统一维护授权应用app_access_token生命周期的位置
          const nowTimestamp = Date.now();
          const expiresTimestamp = nowTimestamp + 15 * 60 * 1000;
          const expiresDate = new Date(expiresTimestamp);
          const expires_in = expiresDate.toISOString();
          //查询删除过期的数据
          log.info({ info: 'expires' });
          const expires = await db.app_access_token.deleteMany({
            where: {
              token_overtime: {
                lt: expires_in
              }
            },
          })

        } else if (message.InfoType == 'authorized') {  //授权成功
          const auth_code = message.AuthorizationCode;

          let AuthorizerApp = await wxopen.getAuthorization(auth_code);
          log.info({ info: 'AuthorizerApp', AuthorizerApp: AuthorizerApp });

        } else if (message.InfoType == 'unauthorized') {  //取消授权


        } else if (message.InfoType == 'updateauthorized') {  //授权更新
          const auth_code = message.AuthorizationCode;

          let AuthorizerApp = await wxopen.getAuthorization(auth_code);
          log.info({ info: 'updateauthorized', AuthorizerApp: AuthorizerApp });

        }

      });
      let response = await wxserver.serve();
      const wxmessage = await wxserver.getDecryptedMessage();
      const wxmessageObj = wxmessage.toObject();
      const componentVerifyTicket = wxmessageObj.ComponentVerifyTicket;

      //   
      res.send('success');

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public server: defaultRouteHandler = async (req, res) => {
    try {
      const { authorizer_id } = req.params;
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const params: Record<string, any> = {};
      params.filter = JSON.stringify({"appid":{"equals":authorizer_id}});
      const wechatopenApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
      const refreshToken = wechatopenApplet[0].authorizer_refresh_token;
      //获取sdk中初始化的公众号应用
      const oaApp = await wxopen.getOfficialAccountWithRefreshToken(authorizer_id, refreshToken);


      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();

      wxserver.with(async function (message) {
       // log.info({ info: 'wxserver.with', message });
        switch (message.MsgType) {
          case 'text':
            // 关键字自动回复
            if (message.Content == '图文') {
              let articles = [
                {
                  title: '测试新闻11',
                  description: '测试新闻描述11',
                  url: 'https://www.baidu.com',
                  image: 'http://img5.imgtn.bdimg.com/it/u=161888459,1712714238&fm=27&gp=0.jpg',
                },
                {
                  title: '测试新闻22',
                  description: '测试新闻描述22',
                  url: 'https://www.baidu.com',
                  image: 'http://img5.imgtn.bdimg.com/it/u=161888459,1712714238&fm=27&gp=0.jpg',
                },
                {
                  title: '测试新闻33',
                  description: '测试新闻描述33',
                  url: 'https://www.baidu.com',
                  image: 'http://img5.imgtn.bdimg.com/it/u=161888459,1712714238&fm=27&gp=0.jpg',
                },
              ];
              /*  let news = new Message({
                  MsgType: 'news',
                  ArticleCount: articles.length,
                  articles,
                });
                return news; */

            }
            else {
            //  return `您说：${message.Content})`;
            }
          case 'event':
            // 消息事件
            switch (message.Event) {
              case 'subscribe':  // 用户关注
              //message.FromUserName是用户的openid
              //message.ToUserName是公众号的原始ID
              //更新公众号用户关注状态
              await db.wechatopen_users.upsert({
                where: {
                  openid: message.FromUserName,
                },
                update: {
                  subscribe: 1
                },
                create: {
                  openid: message.FromUserName,
                  appid: authorizer_id,
                  subscribe: 1

                },
              });


                if (message.EventKey) {
                  const params: Record<string, any> = {};
                  params.filter = JSON.stringify({ appid: authorizer_id, keyword: message.EventKey, type: 1, rule_type: 2, status: 1 });
                  const replyContent = await queryWechatReplysFromDatabase(1, 0, 0, params);

                  return replyContent[0].content;
                }
                break;
              case 'unsubscribe':
                // 用户取关
                //更新公众号用户关注状态
              await db.wechatopen_users.upsert({
                where: {
                  openid: message.FromUserName,
                },
                update: {
                  subscribe: 0
                },
                create: {
                  openid: message.FromUserName,
                  appid: authorizer_id,
                  subscribe: 0

                },
              });
                break;
              case 'CLICK':
                // 菜单点击
                let res = 'success';
                if (message.EventKey == 'TODAY_NEWS') {
                  res = '您点击了【今日新闻】菜单';
                }
                return res;
              case 'SCAN':
                // 用户扫码带参二维码关注
                //带参二维码的场景值为verify
                if (message.EventKey == 'verify') {
                  const params: Record<string, any> = {};
                  params.filter = JSON.stringify({ appid: authorizer_id, keyword: message.EventKey, type: 1, rule_type: 2, status: 1 });
                  const replyContent = await queryWechatReplysFromDatabase(1, 0, 0, params);
                  const snowId = require('simple-flakeid');
                  let gen1 = new snowId.SnowflakeIdv1({ workerId: 1 });
                  const randomString = gen1.NextId().toString();    
                  //截取randomString的后6位
                  const verifyCode = randomString.substr(randomString.length - 6);
                  //查询wechatopen_users表是否有该用户的记录
                  const account = await db.wechatopen_users.findFirst({
                    where: {
                      openid: message.FromUserName,
                    },
                  });
                  const nowTimestamp = Date.now();
                  const date = new Date(nowTimestamp);
                  const withTimezone = date.toISOString();
                  //删除超过10分钟之前的验证码
                  const tenMinutesAgo = new Date(nowTimestamp - 10 * 60 * 1000).toISOString();
                  await db.sms_log.deleteMany({
                    where: {
                      created_at: {
                        lt: tenMinutesAgo
                      }
                    },
                  });
                  //保存验证码到数据库
                  await db.sms_log.create({
                    data: { event: message.EventKey, code: verifyCode, creator: account.id, mobile: "0", created_at: withTimezone },
                  });

                  return `${replyContent[0].content}${verifyCode}`;
                }
                //带参二维码的场景值为login_client_id_前缀
                if (message.EventKey.startsWith("login_client_id_")) {
                  
                  //查询wechatopen_users表是否有该用户的记录
                  const account = await db.wechatopen_users.findFirst({
                    where: {
                      openid: message.FromUserName,
                    },
                  });
                  if (account) {
                    //通过用户wechatopen_users表的帐号查询是否有用户注册
                    const uctooUser = await db.user_has_account.findFirst({
                      where: {
                        account_id: account.id
                      }
                    });
                    if (uctooUser) {
                      //如果已注册，返回组装的登录地址，用户点击登录后进行登录操作
                      const replyContent = `<a href="https://admin.uctoo.com/auth/wechatAuthorization?client_id=${message.EventKey}">点击：确认登录</a>`;
                      return `${replyContent}`;
                    }else{ //如果未注册，返回组装的注册地址，用户点击后进行注册操作
                      return `您还未注册，请注册后登录。`;
                    }
                  }else{//没有公众号用户数据，新增一个
                    await db.wechatopen_users.upsert({
                      where: {
                        openid: message.FromUserName,
                      },
                      update: {
                        subscribe: 1
                      },
                      create: {
                        openid: message.FromUserName,
                        appid: authorizer_id,
                        subscribe: 1
      
                      },
                    });
                  }
                  
                  
                  
                  
                  //返回组装的公众号授权登录地址，用户点击登录后进行登录操作
                  const replyContent = `<a href="https://admin.uctoo.com/auth/wechatAuthorization?client_id=${message.EventKey}">点击：确认登录</a>`;
                  return `${replyContent}`;
                }
                //带参二维码的场景值为resetpassword
                if (message.EventKey == 'resetpassword') {
                  //查询wechatopen_users表是否有该用户的记录
                  const account = await db.wechatopen_users.findFirst({
                    where: {
                      openid: message.FromUserName,
                    },
                  });
                  if (account) {
                    //通过用户wechatopen_users表的帐号查询是否有用户注册
                    const uctooUser = await db.user_has_account.findFirst({
                      where: {
                        account_id: account.id
                      }
                    });
                    if (uctooUser) {
                      const snowId = require('simple-flakeid');
                  let gen1 = new snowId.SnowflakeIdv1({ workerId: 1 });
                  const randomString = gen1.NextId().toString();    
                  //截取randomString的后6位
                  const verifyCode = randomString.substr(randomString.length - 6);
                  //用户状态更新为随机数，重置密码时验证是否一致
                  await db.uctoo_user.update({
                    where: {id: uctooUser.user_id},
                    data: {status: Number(verifyCode)}  }
                  );
                      
                      //回复重置密码页面地址
                  return `https://admin.uctoo.com/auth/resetpassword?user_id=${uctooUser.user_id}&verifyCode=${verifyCode}`;
                    }else{ //如果未注册，返回组装的注册地址，用户点击后进行注册操作
                      return `您还未注册，请注册后登录。`;
                    }
                  }
                  
                }
                
            }
            break;
          default:
        }
        // 返回空或者 'success'，表示程序不做任何响应
        return 'success';
      });

      oaApp.setRequest(request);
      let response = await wxopen.getServer().serve();

      res.setHeader('content-type', response.getHeader('content-type'));
      res.status(200).send(response.getBody());

    } catch (e) {
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public bindcomponent: defaultRouteHandler = async (req, res) => {

    try {
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      log.info({ info: 'wechatopensFromDb', wechatopenFromDb });


      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();

      const codeRes = await wxopen.createPreAuthorizationCode();
      const pre_auth_code = codeRes.pre_auth_code;

      log.info({ info: 'bindcomponent', pre_auth_code });
      const domain = process.env.API_URL;
      const callbackUrl = domain + '/api/wechatopen/authCallback';

      log.info({ info: 'callbackUrl', callbackUrl });
      // 将已生成的pre_auth_code作为参数传入，避免方法内部再次生成
      // 使用类型断言确保TypeScript正确识别返回类型
      //const authUrlRes = await (wxopen.createPreAuthorizationUrl as any)(callbackUrl, pre_auth_code);
      const component_appid = wechatopenFromDb['appid'];
      const encodedRedirectUri = encodeURIComponent(callbackUrl);
      const authType = 3;

      const authUrl = `https://open.weixin.qq.com/wxaopen/safe/bindcomponent?action=bindcomponent&no_scan=1&component_appid=${component_appid}&pre_auth_code=${pre_auth_code}&redirect_uri=${encodedRedirectUri}&auth_type=${authType}#wechat_redirect`;
      // 检查authUrlRes是否有效
      log.info({ info: 'authUrlRes', authUrl});
      
      if (!authUrl || typeof authUrl !== 'string') {
        log.error({ info: 'Invalid authUrlRes', value: authUrl });
        return res.status(500).json({ err: 'Failed to generate authorization URL', desc: 'Invalid URL generated' });
      }

      res.status(200).json({
          authUrl: authUrl
        });

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public authCallback: defaultRouteHandler = async (req, res) => {

    try {
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      log.info({ info: 'wechatopensFromDb', wechatopenFromDb });


      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      // wxopen.setComponentAccessToken(wechatopenFromDb['component_access_token']);  //用数据库维护的component_access_token设置sdk
      const { auth_code, expires_in } = req.query;
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();

      // const codeRes = await wxopen.getAuthorization(auth_code);
      const authCodeString = String(auth_code);
      log.info({ info: 'authCodeString', authCodeString });

      const weapp = (await wxopen.getAuthorization(authCodeString)).toObject();
      log.info({ info: 'authCallback', weapp: weapp.authorization_info });
      log.info({ info: 'weapp', authorizer_appid: weapp.authorization_info.authorizer_appid });
      //保存或更新授权应用信息到wechatopen_applet
      const nowTimestamp = Date.now();
      const date = new Date(nowTimestamp + weapp.authorization_info.expires_in * 1000);  //component_access_token两小时过期
      const nowData = new Date(nowTimestamp);
      const newTokenOvertime = date.toISOString();
      const nowTime = nowData.toISOString();

      let applet = await db.wechatopen_applet.upsert({
        where: {
          appid: weapp.authorization_info.authorizer_appid,
        },
        update: {
          authorizer_access_token: weapp.authorization_info.authorizer_access_token,
          access_token_overtime: newTokenOvertime,
          authorizer_refresh_token: weapp.authorization_info.authorizer_refresh_token,
          func_info: JSON.stringify(weapp.authorization_info.func_info),
          updated_at: nowTime
        },
        create: {
          appid: weapp.authorization_info.authorizer_appid,
          authorizer_access_token: weapp.authorization_info.authorizer_access_token,
          access_token_overtime: newTokenOvertime,
          authorizer_refresh_token: weapp.authorization_info.authorizer_refresh_token,
          func_info: JSON.stringify(weapp.authorization_info.func_info),
          updated_at: nowTime
        },
      });

      //获取应用详细信息
      /* let postData = {component_appid:wechatopenFromDb['appid'],authorizer_appid:weapp.authorization_info.authorizer_appid};
   
       const tokenID = 'open_platform.component_access_token.'+ wechatopenFromDb['appid'];
       const access_token = await Dbcacher.get(tokenID);
       log.info({ info: 'access_token', access_token:access_token });
       log.info({ info: 'component_appid', component_appid:wechatopenFromDb['appid'] });
       log.info({ info: 'authorizer_appid', authorizer_appid:weapp.authorization_info.authorizer_appid });
       const weappInfo = (await client.post('cgi-bin/component/api_get_authorizer_info', {
         
         data: postData
         
     })).toObject(); 
   
   
     
     const aUrl = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?access_token="+access_token;
     log.info({ info: 'aUrl', aUrl:aUrl });
     const weappInfo = await axios.post(
       aUrl,
       JSON.stringify(postData)
     ).then(response => {
       console.log('Success:', response.data);
       log.info({ info: 'axios', Success:response.data });
     })
     .catch(error => {
       log.info({ info: 'axios', Error:error });
       console.error('Error:', error);
     });
   
   
   
     /*  log.info({ info: 'weappInfo', weappInfo:weappInfo });
       applet = await db.wechatopen_applet.upsert({
         where: {
           appid: weapp.authorization_info.authorizer_appid,
         },
         update: {
           name: weappInfo.authorizer_info.nick_name,
           headface_image: weappInfo.authorizer_info.head_img,
           service_type_info: JSON.stringify(weappInfo.authorizer_info.service_type_info),
           verify_type_info: JSON.stringify(weappInfo.authorizer_info.verify_type_info),
           original: weappInfo.authorizer_info.user_name,
           wechat: weappInfo.authorizer_info.alias? weappInfo.authorizer_info.alias:'',
           qrcode_image: weappInfo.authorizer_info.qrcode_url,
           business_info: JSON.stringify(weappInfo.authorizer_info.business_info),
           principal: weappInfo.authorizer_info.principal_name,
           signature: weappInfo.authorizer_info.signature,
           miniprograminfo: weappInfo.authorizer_info.MiniProgramInfo? JSON.stringify(weappInfo.authorizer_info.MiniProgramInfo):'',
           register_type: weappInfo.authorizer_info.register_type,
           status: weappInfo.authorizer_info.account_status,
           basic_config: JSON.stringify(weappInfo.authorizer_info.basic_config),
           channels_info: weappInfo.authorizer_info.channels_info
         },
         create: {
           appid: weapp.authorization_info.authorizer_appid,
           name: weappInfo.authorizer_info.nick_name,
           headface_image: weappInfo.authorizer_info.head_img,
           service_type_info: JSON.stringify(weappInfo.authorizer_info.service_type_info),
           verify_type_info: JSON.stringify(weappInfo.authorizer_info.verify_type_info),
           original: weappInfo.authorizer_info.user_name,
           wechat: weappInfo.authorizer_info.alias? weappInfo.authorizer_info.alias:'',
           qrcode_image: weappInfo.authorizer_info.qrcode_url,
           business_info: JSON.stringify(weappInfo.authorizer_info.business_info),
           principal: weappInfo.authorizer_info.principal_name,
           signature: weappInfo.authorizer_info.signature,
           miniprograminfo: weappInfo.authorizer_info.MiniProgramInfo? JSON.stringify(weappInfo.authorizer_info.MiniProgramInfo):'',
           register_type: weappInfo.authorizer_info.register_type,
           status: weappInfo.authorizer_info.account_status,
           basic_config: JSON.stringify(weappInfo.authorizer_info.basic_config),
           channels_info: weappInfo.authorizer_info.channels_info
         },
       }); */

      res.status(200).json({ "操作结果": "已成功授权" });

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public createJssdkConfig: defaultRouteHandler = async (req, res) => {
    try {
      const reqbody = await req.json();
            log.info(reqbody);
      const authorizer_id = reqbody.appid;
      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });
      log.info({ info: 'wechatopensFromDb', wechatopenFromDb });

      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);
      log.info({ info: 'jssdkConfigurl', url: req.url });
      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: authorizer_id });
      const wechatopenApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
      const refreshToken = wechatopenApplet[0].authorizer_refresh_token;
      //获取sdk中初始化的公众号应用
      const oaApp = await wxopen.getOfficialAccountWithRefreshToken(authorizer_id, refreshToken);
      oaApp.setRequest(request);

      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();

      //生成 JS-SDK 签名 获取工具模块
      const utils = oaApp.getUtils();

      const url = reqbody.url ? reqbody.url : req.url; // 前端需要使用 JSSDK 的完整的 URL 地址
      const jsApiList = reqbody.jsApiList ? JSON.parse(reqbody.jsApiList) : []; // 要使用的接口列表
      const openTagList =  reqbody.openTagList ? JSON.parse(reqbody.openTagList) : []; // 要使用的开放标签列表
      const debug = reqbody.debug ? reqbody.debug : false;  // 是否开启调试模式

      // JSSDK 所需的配置
      const jssdkConfig = utils.buildJsSdkConfig(url, jsApiList, openTagList, debug);
      log.info({ info: 'jssdkConfig', jssdkConfig: jssdkConfig });
      res.status(200).json(jssdkConfig);

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

}

export default uctooWechatopenController;
